#include "common_config_manager.h"
#include "utils_log.h"
#include <fstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <libgen.h>
#include <string.h>
#include <errno.h>
#include <nlohmann/json.hpp>
#include "utils_file_ex.h"

namespace El {
namespace Common {

ConfigManager &ConfigManager::GetInstance()
{
    static ConfigManager instance;
    return instance;
}

ConfigManager::ConfigManager() {}

ConfigManager::~ConfigManager() {}

int32_t ConfigManager::Register(const std::string &path,
                                std::function<bool(const nlohmann::json &)> listener,
                                ConfigPriority priority)
{
    return listeners_[path].Register(listener, static_cast<int32_t>(priority));
}

void ConfigManager::Unregister(const std::string &path, int32_t listenerId)
{
    auto it = listeners_.find(path);
    if (it != listeners_.end()) {
        it->second.Unregister(listenerId);
        if (it->second.IsEmpty()) {
            listeners_.erase(it);
        }
    }
}

// 添加辅助函数用于获取父路径
std::vector<std::string> ConfigManager::GetParentPaths(const std::string &path)
{
    std::vector<std::string> parentPaths;
    size_t pos = 0;

    // 跳过开头的斜杠
    if (!path.empty() && path[0] == '/') {
        pos = 1;
    }

    // 循环提取每个父路径
    while ((pos = path.find('/', pos)) != std::string::npos) {
        parentPaths.push_back(path.substr(0, pos));
        pos++;
    }

    return parentPaths;
}

bool ConfigManager::NotifyListeners(const std::string &path, const nlohmann::json &value)
{
    // 直接路径通知
    auto it = listeners_.find(path);
    if (it != listeners_.end()) {
        // 通过优先级排序的方式调用所有监听器
        bool listenerResult = it->second.InvokeAll(value);
        if (!listenerResult) {
            EL_ERROR("Config listener failed for path: {}", path.c_str());
            return false;
        }
    }

    // 获取所有父路径并通知相关监听器
    std::vector<std::string> parentPaths = GetParentPaths(path);

    for (const auto &parentPath : parentPaths) {
        // 检查父路径是否有监听器
        auto parentListener = listeners_.find(parentPath);

        // 如果没有监听器，跳过处理
        if (parentListener == listeners_.end()) {
            continue;
        }

        // 提取子树，只包含父路径关心的部分
        nlohmann::json subTree;
        try {
            nlohmann::json::json_pointer ptr(parentPath);
            subTree = config_.at(ptr);
        } catch (const std::exception &e) {
            EL_ERROR("Failed to extract subtree for parent path {}: {}", parentPath.c_str(), e.what());
            continue;
        }

        // 通知父路径的监听器
        bool parentListenerResult = parentListener->second.InvokeAll(subTree);
        if (!parentListenerResult) {
            EL_ERROR("Config listener failed for parent path: {}", parentPath.c_str());
            return false;
        }
    }

    // 检查是否有子路径监听器需要通知
    std::string pathPrefix = path;
    if (!pathPrefix.empty() && pathPrefix.back() != '/') {
        pathPrefix += "/";
    }

    // 先检查是否有子路径监听器
    bool hasChildListeners = false;
    for (const auto &listener : listeners_) {
        const std::string &listenerPath = listener.first;
        if (listenerPath != path && listenerPath.substr(0, pathPrefix.length()) == pathPrefix) {
            hasChildListeners = true;
            break;
        }
    }

    // 只有在有子路径监听器时才获取旧值并进行比较
    if (hasChildListeners) {
        // 获取旧配置值用于比较
        nlohmann::json oldValue;
        {
            std::lock_guard<std::mutex> lock(mutex_);
            try {
                nlohmann::json::json_pointer ptr(path);
                if (config_.contains(ptr)) {
                    oldValue = config_.at(ptr);
                }
            } catch (const std::exception &e) {
                // 如果路径不存在，oldValue 保持为空
                EL_DEBUG("Path {} not found in current config, treating as new", path.c_str());
            }
        }

        // 通知所有子路径的监听器（仅在配置确实发生变化时）
        for (auto &listener : listeners_) {
            const std::string &listenerPath = listener.first;

            // 检查是否为子路径（以当前路径为前缀）
            if (listenerPath != path && listenerPath.substr(0, pathPrefix.length()) == pathPrefix) {
                // 提取新配置中子路径对应的配置值
                nlohmann::json newSubValue;
                try {
                    // 计算子路径相对于当前路径的部分
                    std::string relativePath = listenerPath.substr(path.length());
                    if (relativePath[0] == '/') {
                        relativePath = relativePath.substr(1); // 移除开头的斜杠
                    }

                    nlohmann::json::json_pointer ptr("/" + relativePath);
                    newSubValue = value.at(ptr);
                } catch (const std::exception &e) {
                    EL_DEBUG("Child path {} not found in new config, skipping notification", listenerPath.c_str());
                    continue;
                }

                // 提取旧配置中子路径对应的配置值
                nlohmann::json oldSubValue;
                if (!oldValue.is_null()) {
                    try {
                        // 计算子路径相对于当前路径的部分
                        std::string relativePath = listenerPath.substr(path.length());
                        if (relativePath[0] == '/') {
                            relativePath = relativePath.substr(1); // 移除开头的斜杠
                        }

                        nlohmann::json::json_pointer ptr("/" + relativePath);
                        oldSubValue = oldValue.at(ptr);
                    } catch (const std::exception &e) {
                        // 旧值不存在，视为有变化
                        EL_DEBUG("Child path {} not found in old config, treating as changed", listenerPath.c_str());
                    }
                }

                // 只有在配置值真正发生变化时才通知
                if (newSubValue != oldSubValue) {
                    EL_INFO("Child path {} config changed, notifying listener", listenerPath.c_str());

                    // 通知子路径的监听器
                    bool childListenerResult = listener.second.InvokeAll(newSubValue);
                    if (!childListenerResult) {
                        EL_ERROR("Config listener failed for child path: {}", listenerPath.c_str());
                        return false;
                    }
                } else {
                    EL_DEBUG("Child path {} config unchanged, skipping notification", listenerPath.c_str());
                }
            }
        }
    }

    return true;
}

bool ConfigManager::LoadConfig(const std::string &filename, const std::string &defaultConfigFilename)
{
    filename_ = filename;
    defaultFilename_ = defaultConfigFilename;
    if (!LoadConfig(defaultConfigFilename, defaultConfig_)) {
        EL_ERROR("Failed to load default config file: {}", defaultConfigFilename.c_str());
        defaultConfig_ = nlohmann::json::object();
    }

    if (!LoadConfig(filename, config_)) {
        EL_ERROR("Failed to load config file: {}", filename.c_str());
    }

    MergeConfigs(defaultConfig_);
    return true;
}

void ConfigManager::MergeConfigs(const nlohmann::json &defaultConfig)
{
    if (!defaultConfig.is_object()) {
        EL_ERROR("Cannot merge configs: default config is not an object");
        return;
    }

    std::lock_guard<std::mutex> lock(mutex_);
    try {
        for (const auto &[key, value] : defaultConfig.items()) {
            if (config_.find(key) == config_.end()) {
                config_[key] = value;
            }
        }
    } catch (const std::exception &e) {
        EL_ERROR("Exception while merging configs: {}", e.what());
    }
}

bool ConfigManager::LoadConfig(const std::string &filename, nlohmann::json &value)
{
    std::vector<uint8_t> content;
    if (!Utils::LoadFileWithBackup(filename, content)) {
        EL_ERROR("Failed to load config file with backup: {}", filename.c_str());
        return false;
    }

    try {
        // nlohmann::json::parse可以直接处理vector<uint8_t>
        value = nlohmann::json::parse(content, nullptr, false);
        if (value.is_discarded()) {
            EL_ERROR("Failed to parse config content from file: {}", filename.c_str());
            return false;
        }
    } catch (const std::exception &e) {
        EL_ERROR("Exception while parsing config file {}: {}", filename.c_str(), e.what());
        return false;
    }
    return true;
}

nlohmann::json ConfigManager::GetConfig(const std::string &path)
{
    std::lock_guard<std::mutex> lock(mutex_);

    try {
        nlohmann::json::json_pointer ptr(path);
        return config_.at(ptr);
    } catch (const std::exception &e) {
        EL_ERROR("Error setting config with path '{}': {}", path.c_str(), e.what());
        return {};
    }

    EL_ERROR("Key/Path '{}' not found in configs.", path.c_str());
    return {}; // 返回空的 json 对象
}

bool ConfigManager::SetConfig(const std::string &path, const nlohmann::json &value, bool notify)
{
    if (notify && !NotifyListeners(path, value)) {
        EL_ERROR("Notification or validation failed for path: {}", path.c_str());
        return false;
    }

    {
        std::lock_guard<std::mutex> lock(mutex_);
        try {
            nlohmann::json::json_pointer ptr(path);
            config_[ptr] = value;
        } catch (const std::exception &e) {
            EL_ERROR("Error setting config with path '{}': {}", path.c_str(), e.what());
            return false; // 设置时出错
        }
    }

    // 保存配置更改
    if (!SaveConfig(filename_, config_)) {
        EL_ERROR("Failed to save config after setting path: {}", path.c_str());
        // 考虑是否需要回滚更改，但这会增加复杂性
        return false;
    }

    return true;
}

nlohmann::json ConfigManager::GetDefaultConfig(const std::string &path)
{
    std::lock_guard<std::mutex> lock(mutex_);

    try {
        nlohmann::json::json_pointer ptr(path);
        // 使用 at() 以便在路径无效时抛出异常
        return defaultConfig_.at(ptr);
    } catch (const std::exception &e) {
        EL_DEBUG("Error setting config with path '{}': {}", path.c_str(), e.what());
        return {};
    }
}

bool ConfigManager::SetDefaultConfig(const std::string &path, const nlohmann::json &value)
{
    bool configModified = false;
    {
        std::lock_guard<std::mutex> lock(mutex_);
        try {
            nlohmann::json::json_pointer ptr(path);
            
            // 设置默认配置
            defaultConfig_[ptr] = value;
            
            // 获取或创建当前配置中的目标路径
            if (!config_.contains(ptr)) {
                config_[ptr] = nlohmann::json::object();
                configModified = true;
            }
            
            // 递归合并默认值到当前配置
            nlohmann::json &targetConfig = config_[ptr];
            nlohmann::json originalConfig = targetConfig; // 保存原始配置用于比较
            RecursiveMergeDefaults(targetConfig, value);
            
            // 检查是否有修改
            if (targetConfig != originalConfig) {
                configModified = true;
            }
            
        } catch (const std::exception &e) {
            EL_ERROR("Error in SetDefaultConfig with path '{}': {}", path.c_str(), e.what());
            return false;
        }
    }
    
    // 如果配置有修改，保存配置文件
    if (configModified) {
        if (!SaveConfig(filename_, config_)) {
            EL_ERROR("Failed to save config after setting default for path: {}", path.c_str());
            return false;
        }
        EL_DEBUG("Recursively merged default config for path: {}", path.c_str());
    }
    
    return true;
}

bool ConfigManager::SaveConfig(const std::string &filename, const nlohmann::json &config)
{
    std::string contentStr = config.dump(4);
    std::vector<uint8_t> content(contentStr.begin(), contentStr.end());
    if (!Utils::SaveFileWithBackup(filename, content)) {
        EL_ERROR("Failed to save config to file: {}", filename.c_str());
        return false;
    }
    return true;
}

bool ConfigManager::ResetToFactory()
{
    std::lock_guard<std::mutex> lock(mutex_);

    try {
        // 将默认配置复制到当前配置
        config_ = defaultConfig_;

        // 保存重置后的配置到文件
        if (!SaveConfig(filename_, config_)) {
            EL_ERROR("Failed to save factory reset config to file: {}", filename_.c_str());
            return false;
        }

        EL_INFO("Factory reset completed successfully");
        return true;

    } catch (const std::exception &e) {
        EL_ERROR("Exception while performing factory reset: {}", e.what());
        return false;
    }
}

void ConfigManager::RecursiveMergeDefaults(nlohmann::json &target, const nlohmann::json &defaults)
{
    // 如果默认值不是对象类型，直接设置
    if (!defaults.is_object()) {
        target = defaults;
        return;
    }

    // 如果目标不是对象类型，将其初始化为空对象
    if (!target.is_object()) {
        target = nlohmann::json::object();
    }

    // 递归遍历默认配置的每个键值对
    for (const auto &[key, value] : defaults.items()) {
        if (target.find(key) == target.end()) {
            // 如果目标中不存在该键，直接复制默认值
            target[key] = value;
        } else if (value.is_object() && target[key].is_object()) {
            // 如果两者都是对象，递归合并
            RecursiveMergeDefaults(target[key], value);
        }
        // 如果目标中已存在该键且不是对象类型，保持目标值不变
    }
}

} // namespace Common
} // namespace El